<?php

declare (strict_types=1);
/**
 * @copyright 深圳市易果网络科技有限公司
 * @version 1.0.0
 * @link https://dayiguo.com
 */

namespace App\Service\User;

use App\Dao\GoodsDao;
use App\Dao\IntegralDetailDao;
use App\Dao\LogisticDao;
use App\Dao\OrderItemDao;
use App\Dao\PaymentDao;
use App\Dao\UserBillDao;
use App\Dao\UserDao;
use App\Exception\CustomException;
use App\Job\IntegralJob;
use App\Kernel\Util\UserJwtInstance;
use App\Service\Service;
use App\Dao\UserAddrDao;
use App\Dao\GoodsSkuDao;
use App\Dao\OrderDao;

use Hyperf\DbConnection\Db;
use Hyperf\Snowflake\IdGeneratorInterface;
use Hyperf\Di\Annotation\Inject;

/**
 * 订单服务
 *
 * @author 谢声强(861167322@qq.com)
 * @package App\Service\User
 */
class OrderService  extends Service
{
    /**
     * 用户地址 DAO
     *
     * @Inject()
     * @var UserAddrDao
     */
    private $user_addr_dao;

    /**
     * @Inject
     * @var PaymentDao
     */
    private $payment_dao;

    /**
     * 商品 SKU DAO
     *
     * @Inject()
     * @var GoodsSkuDao
     */
    private $goods_sku_dao;

    /**
     * @Inject
     *
     * @var PingPpService
     */
    private $ping_service;

    /**
     * 订单 DAO
     *
     * @Inject()
     * @var OrderDao
     */
    public $dao;

    /**
     * @Inject
     * @var GoodsDao
     */
    public $goods_dao;

    /**
     * @Inject
     * @var UserBillDao
     */
    public $user_bill_dao;

    /**
     * @Inject
     * @var UserDao
     */
    public $user_dao;

    /**
     * @Inject
     * @var IntegralDetailDao
     */
    public $integral_detail_dao;

    /**
     * @Inject
     * @var OrderItemDao
     */
    public $order_item_dao;


    /**
     * 物流Dao
     * @Inject()
     * @var LogisticDao
     */
    public $logistics_dao;

    /**
     * @var int
     */
    const STATUS_TO_CANCEL = 6;

    /**
     * @var int
     */
    const STATUS_TO_CLOSE = 7;


    /**
     * 未支付订单 - 重新支付
     * @param int $order_id
     * @param string $channel
     * @return mixed
     */
    public function unpaid(int $order_id, string $channel)
    {
        $order = $this->dao->getFirstOrder($order_id);

        if($order['user_id'] !== uid()) {
            $this->error("ORDER.USER_NOT_EXIST_ORDER");
        }

        if( $order->status !== $this->dao::STATUS_UNPAID ){
            $this->error("ORDER.STATUS_UNPAID");
        }

        $result = [
            'user_id' => uid(),
            'value' => $order->order_no,
            'amount' => $order->price,
            'type' => 1,
            'channel' => $channel
        ];
        $payment = $this->ping_service->pay($result, $channel,  "商品下单", '订单支付');

        return [
            'payment' =>  $payment,
        ];
    }

    /**
     * 订单列表数据处理
     * @param array $map
     * @return mixed
     */
    public function list(array $map)
    {
        $result = $this->dao->get( $map );

        return $result;
    }


    /**
     * 商品下单
     *
     * @author 刘兴永(aile8880@qq.com)
     * @date 2020-02-28 19:57:00
     * @param array $params
     * @return array
     */
    public function  buy(array $params)
    {
        $addr = $this->user_addr_dao->first($params['addr_id']);
        $order_no = (string)$this->container->get(IdGeneratorInterface::class)->generate();

        $order_items = [];
        $total_price = $price = $integral = 0;

        if(($sku_id = (int)$params['sku_id'] ?? 0) === 0)  $this->error();
        $num = abs($params['num'] ?? 1);

        // 获取SKU
        if( $params['type'] == 1 ) {
            if (!$sku = $this->goods_sku_dao->first(['id' => $sku_id]))  $this->error();
        } else {
            $goods = $this->goods_dao->getGoodsById($sku_id);
            $sku = $this->goods_sku_dao->loginByPhoneOrCreate($sku_id,'默认',$goods['price'],$goods['integral'],[330],$goods['picture']);
            //if (!$sku = $this->goods_sku_dao->first(['goods_id' => $sku_id]))  $this->error();
        }

        // 获取商品
        if (!$goods = $sku->goods)  $this->error();

        // 判断库存
        if ($sku->stock < $num || $goods->stock < $num)  $this->error();

        // 判断商品上下架
        if ($goods->is_marketable !== 1)  $this->error();

        $order_items[] = [
            'goods_id' => $goods->id,
            'goods_name' => $goods->title,
            'order_no' => $order_no,
            'num' => $num,
            'price' => $sku->price,
            'original_price' => $goods->original_price,
            'integral' => $integral,
            'sku_id' => $sku->id,
            'sku_name' => $sku->name,
            'sku_picture' => $sku->picture,
            'sku_weight' => $sku->weight
        ];

        $price = $sku->price; // 订单实际需支付价格
        $total_price += ($goods->original_price * $num); // 订单原价总和
        $integral += ($sku->integral * $num); // 总需使用积分

        $order = [
            'user_id' => uid(),
            'order_no' => $order_no,
            'total_price' => $total_price,
            'price' => $price,
            'integral' => $integral,
            'remark' => $params['remark'] ?? '',
            'express_name' => $addr['name'],
            'express_phone' => $addr['phone'],
            'express_address' => $addr['province'] . $addr['city'] . $addr['district'] . $addr['address'],
            'status' => $price <= 0 ? 1 : 0 // 如果不需要现金，那么订单状态直接设为已支付
        ];

        if (count($order_items) === 0) {
            $this->error('ORDER.NOT_VALID_GOODS');
        }

        $this->dao->createOrder($order, $order_items, $goods->title, $sku->picture);

        if( $price > 0 ) {
            $result = $this->pay($order_no);
            $payment = $this->ping_service->pay($result, $params['channel'],  "商品下单", '订单支付');
            return [
                'goods_type' => '2',
                'order_no' => $order_no,
                'payment' =>  $payment,
            ];
        }

        return [
            'goods_type' => '1',
            'order_no' => $order_no,
        ];
    }

    /**
     * 订单支付
     *
     * @author 刘兴永(aile8880@qq.com)
     * @date 2020-02-28 19:57:00
     * @param string $order_no
     * @param int $type
     * @return array
     */
    public function pay(string $order_no, int $type = 1)
    {
        $order = $this->dao->find([
            ['user_id' => uid()],
            ['order_no' => $order_no]
        ], ['id', 'price', 'status'], null, 'ORDER.NOT_EXIST');

        // 已支付
        if ($order->status === 1) {
            $this->error('ORDER.ORDER_PAID');
        }

        // 订单是否需要支付
        if ($order->price <= 0) {
            $this->error('ORDER.NOT_REQUIRED_PAY');
        }

        // 非待支付状态无法进行付款
        if ($order->status !== 0) {
            $this->error('ORDER.STATUS_EXCEPTION');
        }

        // 在线支付
        if ($type === 1) {
            return [
                'user_id' => uid(),
                'value' => $order_no,
                'amount' => $order->price,
                'type' => 1,
            ];
        }

        return [];
    }

    /**
     * 关闭订单
     *
     * @author 刘兴永(aile8880@qq.com)
     * @date 2020-02-28 19:57:00
     * @param string $order_no
     * @param int $status
     * @param string $remark
     */
    public function closeOrder(string $order_no, int $status, string $remark = '')
    {
        Db::beginTransaction();
        try {
            $order = $this->dao->find([
                ['order_no' => $order_no]
            ], ['id', 'user_id', 'order_no', 'integral', 'status']);
            if (!$order) throw new CustomException('ORDER.NOT_EXIST');
            if ($order->status != 0) throw new CustomException('ORDER.STATUS_EXCEPTION');

            $order->status = $status;
            $order->remark = $remark;
            if (!$order->save()) {
                throw new CustomException('ORDER.UPDATE_FAIL');
            }

            foreach ($order->items as $item) {
                // 退还商品库存
                $this->goods_dao->addStock($item->goods_id, $item->num);
                // 退还SKU库存
                $this->goods_sku_dao->addStock($item->sku_id, $item->num);
            }
            $orderItem = $this->order_item_dao->find(['order_no' => $order_no],['goods_name','sku_picture']);
            if ($order->integral > 0) {
                // 退还用户积分
                $this->user_dao->increment($order->user_id, $order->integral, $this->user_dao::INTEGRAL);
                // 积分记录
                $this->integral_detail_dao->create([
                    'status' => 5,
                    'type' => 1,
                    'user_id' => $order->user_id,
                    'num' => $order->integral,
                    'remark' => '订单关闭退还',
                    'order_no' => $order->order_no,
                    'goods_name' => $orderItem->goods_name,
                    'goods_pic' => $orderItem->sku_picture,
                ]);
                $this->driver->push(new IntegralJob( $order->user_id ));
            }

            Db::commit();
        }
        catch (CustomException $e) {
            Db::rollBack();
            $this->logger('order')->error($e->getMessage(), ['closeOrder']);
            $this->error('');
        }
        catch (\Exception $e) {
            Db::rollBack();
            $this->error('COMMON.SYSTEM_ERROR');
        }
    }

    /**
     * 积分商城回调
     * @param $params
     */
    public function pingNotify( $params )
    {
        $payment['pay_no'] = substr($params['order_no'],5);
        $payment['status'] = $this->dao::STATUS_UNPAID;
        $payments = $this->payment_dao->getPaymentByMap( $payment );
        if( !$payments ) {
            return false;
        }
        $payments->status = $this->dao::STATUS_PAID;
        $payments->trade_no = $params['transaction_no'];
        $payments->updated_at = time();
        if( $payments->save() ) {
            $where['order_no'] = $payments['value'];
            $where['status'] = $this->dao::STATUS_UNPAID;
            $order = $this->dao->getOrderByMap($where);
            $order->status = $this->dao::STATUS_PAID;
            $order->pay_time = time();
            $order->updated_at = time();
            $order->save();
        }
    }

    /**
     * 确认是否可以自动完成订单
     * @param string $order_no
     */
    public function confirm(string $order_no)
    {
        $logistic = $this->logistics_dao->getLogisticByOrderNo($order_no);
        !$logistic && $this->logger("order")->error("订单编号为：{$order_no}的物流不存在");

        $order = $this->dao->getFirstOrderByNo($order_no);
        !$order && $this->logger("order")->error("订单编号为：{$order_no}的订单不存在");

        if ($logistic->status == 3 && $order->status == 2) {
            $order->status = 3;
            $result = $order->save();
            !$result && $this->logger("order")->error("订单编号为：{$order_no}的订单状态保存失败");
        }

    }
    
    
}